package com.atguigu.spzx.pay.service.Impl;

import cn.hutool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.domain.PageInfo;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.atguigu.spzx.feign.order.OrderFeignClient;
import com.atguigu.spzx.model.entity.order.OrderInfo;
import com.atguigu.spzx.model.entity.pay.PaymentInfo;
import com.atguigu.spzx.model.exception.GuiguException;
import com.atguigu.spzx.model.vo.common.Result;
import com.atguigu.spzx.model.vo.common.ResultCodeEnum;
import com.atguigu.spzx.pay.config.AlipayConfig;
import com.atguigu.spzx.pay.service.AlipayService;
import com.atguigu.spzx.pay.service.PaymentInfoService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Map;

/**
 * @author LT
 * @create 2024-04-01-19:21
 */
@Slf4j
@Service
public class ApipayServiceImpl implements AlipayService {
    @Resource
    PaymentInfoService paymentInfoService;
    @Resource
    OrderFeignClient orderFeignClient;

    @Override
    public String submitAlipy(Long orderNo) {
        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = ""+orderNo;
        Result<OrderInfo> result = orderFeignClient.getByOrderInfoOrderNo(orderNo);
        if (result.getCode().intValue() != 200){
            throw new GuiguException(ResultCodeEnum.ERROR);
        }
        OrderInfo orderInfo = result.getData();
        if (orderInfo.getOrderStatus().intValue()!=0){
            throw new GuiguException(ResultCodeEnum.ERROR);
        }

        // 订单名称，必填
        String subject = orderInfo.getOrderItemList().stream().map(orderItem -> orderItem.getSkuName())
                .reduce((skuName,skuName1) -> skuName+" "+skuName1).get();
        // 付款金额，必填
        String total_amount=orderInfo.getTotalAmount().toString();
        // 商品描述，可空
        String body = orderInfo.getOrderItemList().stream().map(orderItem -> orderItem.getSkuName())
                .reduce((skuName,skuName1) -> skuName+" "+skuName1).get();
        // 销售产品码 必填
        String product_code="QUICK_WAP_WAY";
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        //需要修改为沙箱环境的参数
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL,
                AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY,
                AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);
        AlipayTradeWapPayRequest alipay_request=new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setBody(body);
        model.setProductCode(product_code);
        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址
        alipay_request.setReturnUrl(AlipayConfig.return_url);

        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单
            form = client.pageExecute(alipay_request).getBody();
            System.out.println(form);
            //返回支付宝支付自动提交的表单字符串
            PaymentInfo paymentInfo = new PaymentInfo();
            //使用订单中的用户Id
            paymentInfo.setUserId(orderInfo.getUserId());
            paymentInfo.setOrderNo(orderInfo.getOrderNo());
            paymentInfo.setPayType(2);
            paymentInfo.setAmount(orderInfo.getTotalAmount());
            paymentInfo.setContent(subject);
            paymentInfo.setPaymentStatus("0");//待支付
            paymentInfoService.saveAsync(paymentInfo);
            return form;
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new GuiguException(ResultCodeEnum.PAY_ALIPAY_ERROR);
        }
    }

    @Override
    public String notifyUrl(Map<String, String> params) {
        try {
            //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            //商户订单号
            String out_trade_no = params.get("out_trade_no");
            //支付宝交易号

            String trade_no = params.get("trade_no");

            //交易状态
            String trade_status = params.get("trade_status");

            //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            //计算得出通知验证结果
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");

            if(verify_result){//验证成功
                //////////////////////////////////////////////////////////////////////////////////////////
                //请在这里加上商户的业务逻辑程序代码

                //——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

                if(trade_status.equals("TRADE_FINISHED")){
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    //如果有做过处理，不执行商户的业务程序
                    //注意：
                    //如果签约的是可退款协议，退款日期超过可退款期限后（如三个月可退款），支付宝系统发送该交易状态通知
                    //如果没有签约可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
                } else if (trade_status.equals("TRADE_SUCCESS")){
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                    //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    //如果有做过处理，不执行商户的业务程序
                    //TODO：获取初始支付日志： 幂等性和支付金额校验: out_trade_no
                    PaymentInfo paymentInfo = paymentInfoService.getByOrderNo(out_trade_no);
                    if (paymentInfo==null){
                        return "fail";
                    }
                    String paymentStatus = paymentInfo.getPaymentStatus();
                    if (!"0".equals(paymentStatus)){
                        return "success";
                    }
                    BigDecimal amount = paymentInfo.getAmount();

                    BigDecimal buyerPayAmount = new BigDecimal(params.get("buyer_pay_amount"));
                    paymentInfo.setOutTradeNo(trade_no);
                    if (amount.compareTo(buyerPayAmount)!=0){
                        paymentInfo.setPaymentStatus("4");
                    }
                    paymentInfo.setPaymentStatus("1");
                    paymentInfoService.updatePaymentStatus(paymentInfo);
                    PaymentInfo info = paymentInfoService.getByOrderNo(paymentInfo.getOrderNo());
                    if (info.getPayType()!=0 &&info.getPayType()!=null){
                        info.setPaymentStatus("1");
                    }
                    orderFeignClient.updatePayTypeAndOrderStatus(info.getPayType(),info.getPaymentStatus(),paymentInfo.getOrderNo());
                    orderFeignClient.updateStockAndSale(paymentInfo.getOrderNo());
                    return "success";
                    //注意：
                    //如果签约的是可退款协议，那么付款完成后，支付宝系统发送该交易状态通知。
                }
                //////////////////////////////////////////////////////////////////////////////////////////
            }else{//验证失败
                return "fail";
            }
            return "success";
        } catch (AlipayApiException e) {
            log.error("支付宝回调失败，回调参数：{} , 原因：{}" , JSON.toJSONString(params), ExceptionUtils.getStackTrace(e));
        }
        return "fail";
    }

}
